
import { Singleton } from "./Common";

export default class stringTool extends Singleton<stringTool>{
    // private property
    private _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    constructor(){
        super();
    }
    
    /**
     * 从字符串中提取中括号中间的字符串
     * @param str 
     * @returns 
     */
     public getMatchedStrs(str:string):string{
        var reg = /\[(.+?)\]/
        var reg_g = /\[(.+?)\]/g
        var result = str.match(reg_g)
        var list = []
        for (var i = 0; i < result.length; i++) {
            var item = result[i]
            list.push(item.match(reg)[1])
        }
        return list.toString();
    }
    /**
     * 从字符串中提取大括号中间的字符串
     * @param str 
     * @returns 
     */
    public getMatchedStrs2(str:string):string{
        var reg = /\{(.+?)\}/
        var reg_g = /\{(.+?)\}/g
        var result = str.match(reg_g)
        var list = []
        for (var i = 0; i < result.length; i++) {
            var item = result[i]
            list.push(item.match(reg)[1])
        }
        return list.toString();
    }
    /**
     * 从字符串中提取小括号中间的字符串
     * @param str 
     * @returns 
     */
     public getMatchedStrs3(str:string):string{
        var reg = /\((.+?)\)/
        var reg_g = /\((.+?)\)/g
        var result = str.match(reg_g)
        var list = []
        for (var i = 0; i < result.length; i++) {
            var item = result[i]
            list.push(item.match(reg)[1])
        }
        return list.toString(); 
    }
    public insertStr(soure:string, start:number, newStr:string){   
        return soure.slice(0, start) + newStr + soure.slice(start);
    }
    public insertStrByIndex(src:string,len:number=3,division:string=","){
        let index:number=0;
        for(let i=src.length - 1;i >= 0;i--){
            index++; 
            if(index % len == 0){ 
                index=0;
                src = this.insertStr(src,i,",")
            }
        } 
        if(src.indexOf(",")==0)src=src.substr(1,src.length-1);
        return src;
    }
    public toFixed(value:number,wei:number=3){
        let valueStr:string=value.toString();
        let n:number=valueStr.indexOf(".");
        if(n>=0){
            return valueStr.substr(0,(n+wei+1));
        }
        return valueStr;
    }
    public numberToSpecialStr(value:number,wei:number=2,isUnit:Boolean=true):string{ 
        let str=value.toString();
        let tempStr:string="";  
        if(isUnit){
            if(str.length >= 5 && str.length < 9){  
                // str=(value / 10000).toFixed(wei)+"万"; 
                str=this.toFixed(value / 10000,wei)+"万"; 
            }else if(str.length >= 9){  
                str=this.toFixed(value / 100000000,wei)+"亿"
            }
            let temp:string[]=str.split("."); 
            for(let i=0;i<temp.length;i++){
                let sr:string = this.insertStrByIndex(temp[i]);
                tempStr += sr;
                if(i==0 && temp.length > 1)tempStr+="."
            }  
        }else{
            tempStr=this.insertStrByIndex(str);
        }
        return tempStr; 
    }
    public getSpecialStr(str:string):string{
        if(str.length<=0)return "";
        let str1:string="";
        while(str.indexOf("[") >= 0 && str.indexOf("]") >= 0){
            str1=this.getMatchedStrs(str);
            str = str.replace("["+str1+"]","<color=#c38134>"+str1+"</color>")
        }
        while(str.indexOf("{") >= 0 && str.indexOf("}") >= 0){
            str1=this.getMatchedStrs2(str);
            str = str.replace("{"+str1+"}","<color=#ff2d2d>"+this.formattedNumber(parseFloat(str1))+"</color>")
        }
        while(str.indexOf("(") >= 0 && str.indexOf(")") >= 0){
            str1=this.getMatchedStrs3(str);
            str = str.replace("("+str1+")","<color=#c38134>"+this.formattedNumber(parseFloat(str1))+"</color>")
        }
        return str;
    }
    
    public toUint8AyyayByStr(str:string){
        const buffer = [];
        for (let i of str) {
            const _code = i.charCodeAt(0);
            if (_code < 0x80) {
                buffer.push(_code);
            } else if (_code < 0x800) {
                buffer.push(0xc0 + (_code >> 6));
                buffer.push(0x80 + (_code & 0x3f));
            } else if (_code < 0x10000) {
                buffer.push(0xe0 + (_code >> 12));
                buffer.push(0x80 + (_code >> 6 & 0x3f));
                buffer.push(0x80 + (_code & 0x3f));
            }
        }
        return Uint8Array.from(buffer);
    }

    /**
     * 获取字符串的长度，区分中英文
     * @param str 
     */
    public strleng(str:string){
        var l:number = str.length;
        var blen:number = 0;
        for(let i:number=0; i<l; i++) {
            if ((str.charCodeAt(i) & 0xff00) != 0) {
                blen ++;
            }
            blen ++;
        }
        return blen;
    }

    // base64编码
    public encode64(src:string|Object):string {
        let _src:string = typeof src === 'object' ? JSON.stringify(src):src;
        if (!this._isNotBase64(_src))return _src;
        let output = '';
        let chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        let i = 0;
        _src = this.encodeUTF8(_src);
        while (i < _src.length) {
            chr1 = _src.charCodeAt(i++);
            chr2 = _src.charCodeAt(i++);
            chr3 = _src.charCodeAt(i++);
            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;
            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }
            output = output +
                this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
        }
        return output;
    }

    // base64解码
    public decode64(src:string):string {
        if (this._isNotBase64(src)) return src;
        let output = '';
        let chr1, chr2, chr3;
        let enc1, enc2, enc3, enc4;
        let i = 0;
        src = src.replace(/[^A-Za-z0-9\+\/\=]/g, '');
        while (i < src.length) {
            enc1 = this._keyStr.indexOf(src.charAt(i++));
            enc2 = this._keyStr.indexOf(src.charAt(i++));
            enc3 = this._keyStr.indexOf(src.charAt(i++));
            enc4 = this._keyStr.indexOf(src.charAt(i++));
            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;
            output = output + String.fromCharCode(chr1);
            if (enc3 !== 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 !== 64) {
                output = output + String.fromCharCode(chr3);
            }
        }
        output = this.decodeUTF8(output);
        return output;
    }

    // private method for UTF-8 encoding
    public encodeUTF8(src:string):string {
        src = src.replace(/\r\n/g, '\n');
        let utftext = '';
        for (let n = 0; n < src.length; n++) {
            const c = src.charCodeAt(n);
            if (c < 128) {
                utftext += String.fromCharCode(c);
            } else if ((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            } else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }
        return utftext;
    }

    // private method for UTF-8 decoding
    public decodeUTF8(utftext:string):string {
        let string = '';
        let i = 0;
        let c = 0, c2 = 0, c3 = 0;
        while (i < utftext.length) {
            c = utftext.charCodeAt(i);
            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            } else if ((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i + 1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            } else {
                c2 = utftext.charCodeAt(i + 1);
                c3 = utftext.charCodeAt(i + 2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }
        }
        return string;
    }

	/**
	 * 数字每隔三位加个逗号
	 * @param value 
	 * @returns 
	 */
    public formattedNumber(value:number,isUnit:boolean = true):string {
		let str:string = ""
		var scen:string;
		let coun:number = 1;
		if(isUnit){
			if(value>99999999){
				coun = 100000000;
				str = "亿";
				scen = '0'
			}else if(value>9999){
				coun = 10000;
				str = "万";
				scen= '0'
			}
		}
		let toFixed=(value:number,wei:number=3)=>{
			let valueStr:string=value.toString();
			let n:number=valueStr.indexOf(".");
			if(n>=0){
				return valueStr.substr(0,(n+wei+1));
			}
			return valueStr;
		}
		let num = value.toString()
		if((value %coun)>=1){
			num = value==0?"0":(value /coun).toString();
			num = toFixed(parseFloat(num),2)
		}else{
			num = (value /coun)+"";
		}
		let frist:string;
		if(num.indexOf(".")>=0){
			frist = num.split(".")[0];
			scen = num.split(".")[1];
		}else {
			frist = num;
		}
		let result = '';
		while (frist.length > 3) {
			result = ',' + frist.slice(-3) + result;
			frist = frist.slice(0, frist.length - 3);
		}
		if (frist) { result = frist + result; }
		if(scen) result = result +"."+(scen.length<2?scen+"0":scen);
		result+=str;
		return result;
	}

    private _isNotBase64(str:string):boolean{
        const len = str.length;
        if (!len || len % 4 !== 0 || (new RegExp('/[^A-Z0-9+\/=]/i')).test(str)) {
          return true;
        }
        const firstPaddingChar = str.indexOf('=');
        return firstPaddingChar === -1 ||
          firstPaddingChar === len - 1 ||
          (firstPaddingChar === len - 2 && str[len - 1] === '=');
    }
}